iT邦幫忙

2021 iThome 鐵人賽

DAY 3
1
Modern Web

三十天成為D3.js v7 好手系列 第 3

Day3-認識 SVG

  • 分享至 

  • xImage
  •  

本篇大綱:DOM 元素、SVG 重點概述、SVG 形狀/線條/路徑/文字、SVG樣式

上一章有提過在學習D3之前需要具備的知識,這邊就來講解其中最重要的一點:SVG!由於 D3.js 的畫面渲染部分是用 SVG 運作,因此如果完全不懂 SVG 的話,就無法順利使用 D3 了~現在來說說 SVG 是什麼吧!

先來說說 DOM 元素(Document Object Model)

在講SVG之前,我們需要先了解 html DOM樹 的概念。為什麼得要先了解DOM呢? 主要是因為 D3 是靠著操作 DOM 元素來進行node節點增減,再透過 SVG 去渲染圖表

DOM 的全名是 Document Object Model,中文叫做文件物件模型。聽起來好像很複雜抽象,但其實就是把 HTML 文件中的每個標籤都定義成物件,最後這些物件會形成像是樹狀的結構。像下圖就是一個基本的html文件樹狀圖:
https://ithelp.ithome.com.tw/upload/images/20210915/201349306TPKBBfOQw.jpg

所以如果你的程式碼長這樣

<div>
    <div class="box">
        <div class="box1"></div>
        <div class="box2"></div>
    </div>
    <div class="list">
        <ul>
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </div>
</div>

你的 DOM 樹結構就會是這樣
https://ithelp.ithome.com.tw/upload/images/20210915/201349300R8MfE3cWR.jpg

這裡的每一個 html 標籤就視為一個 node 節點,D3 是將數據資料綁定到節點,並增減節點來建立圖表。

然後呢?快說 SVG!

有了以上的 DOM 概念後,我們就可以來看SVG啦!SVG 的全名是 Scale Vector Graphics (可縮放向量圖型),是以** XML 文字檔來建立 2D 的向量圖形**,因此開發者可以直接在 HTML 檔案中使用 SVG,而且也支援動畫跟互動的操作。

SVG 圖形可以有不同的形式

  • 獨立的文件 ⇒ 比較少見
  • 包在 HTML 檔案中 ⇒ 最常見,為 < svg > < /svg >元素
  • 當作圖片來源引入 ⇒ < img src="smile.svg" >

D3.js使用的就是第二種形式,在 html 檔案中使用svg標籤,並宣告它的空間範圍。接著在這個範圍內放入要繪製的圖形元素標籤,以及它的位置、顏色等等相關資訊

<svg width="500" height="500">
	 這邊放入要繪製的圖形元素標籤...
</svg>

SVG 的重點概述

了解SVG之後,我們來看一下SVG的一些基本概念

  1. SVG 是基於 XML 文字檔格式,產生DOM樹 (不像canvas是平面畫布)

  2. SVG 定義了一系列圖形元素,例如「圓或矩形等基本形狀、文字、直線、曲線」等等,然後再透過外觀屬性去改變這些形狀的尺寸、位置、顏色等等

    例如:svg 定義的 < rect > 矩形元素,< rect > 透過外觀屬形 x, y 去控制圖形位置;width, height 控制圖形大小;style 則控制邊框、顏色

<svg width="400" height="200" style="border:1px solid red">
    <rect x="20" y="20" width="300" height="100" 
          style="fill:rgb(255, 0, 255); stroke-width:3; stroke:rgb(0,0,0)" />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930wrArcKnDh7.jpg

  1. 除了形狀之外,svg 也有許多結構元素,例如: < svg >、 < g >、< use >。大家在看別人的 svg 程式碼時,應該蠻常看到下圖 這個元素,它就是其中一種 SVG 的結構元素
    https://ithelp.ithome.com.tw/upload/images/20210915/20134930Hd82vIv1Vz.jpg

那你可能就會問,什麼是結構元素呢?結構元素是一種容器元素,不會繪製外型,而是用來包裹多個子元素,這樣一來就能將其下的子元素包成一個大包的共同元素,統一去改變位置、形狀或顏色等等。

我們可以簡單整理一下結構元素的特點:

  • 套用到結構元素上的屬性(移動、換色)會同步套用到子項目
  • 沒有形狀,負責組裝複雜圖形物件成為共同集合,並可一次移動與操作這個圖形集合
  1. 跟一般的 html 撰寫一樣,SVG 也是按照文件的順序進行渲染,所以後來寫的元素會遮蓋掉先前出現的元素
  2. SVG 使用的是圖形座標,因此原點是左上角,由上而下、從左至右
  3. SVG 可以接收使用者事件,並回應事件進行互動
  4. SVG 圖形原則上是無限大,width / height 只是定義 viewport (可視範圍)。
    這點很重要,正因為 svg 圖形原則上是無限大,所以如果圖案超過 svg 的可視範圍,圖案一樣存在只是我們看不到而已

https://ithelp.ithome.com.tw/upload/images/20210915/20134930RYDACwGEQk.jpg

但是不可能所有數據都剛好符合我們設定的視窗比例,這也正是為什麼、要定義比例尺的原因。透過比例尺去定義出視窗大小跟數據的比例,才能將繪製完的圖形完整放到我們的 svg 視窗內。

看完這些之後,相信大家對 SVG 已經有概念了。接下來我們來看看 SVG 定義的一些形狀、線條、路徑,以及它們的屬性吧!

SVG 形狀

svg 已經先幫我們定義好一些形狀,並賦予相對應的標籤。我們只要使用這些標籤,並添加固定的屬性,就可以畫出一些基本的形狀啦~這些定義好的形狀包含:

  • < rect > 矩形
屬性 意義
x, y 左上角座標寬、高
width, height 寬高
rx, ry 水平/垂直邊角半徑

範例:從坐標軸 x 20 與 y 20 的地方開始,建立一個寬300、高100的長方形;內部填滿桃紅色,並且要有3px的粗黑邊框

<svg width="400" height="200" style="border:1px solid red">
    <rect x="20" y="20" width="300" height="100" 
          style="fill:rgb(255, 0, 255); stroke-width:3; stroke:rgb(0,0,0)" />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930kdZi9467wO.jpg

  • < circle > 圓形
屬性 意義
cx, cy 水平/垂直中心座標
r 半徑

範例:從坐標軸 x 100 與 y 50 的地方開始,建立一個半徑為40的圓型,內部填滿紅色,且要有3px的粗黑邊框

<svg width="400" height="150" style="border:1px solid red">
  <circle cx="100" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930fldzFvNP43.jpg

  • < ellipse > 橢圓形
屬性 意義
cx, cy 中心座標水平
rx, ry 垂直半徑

範例:從坐標軸 x 200 與 y 80 的地方開始,建立一個x半徑為80、y半徑為50的橢圓型,內部填滿淡粉紅色,且要有3px的粗黑邊框

<svg width="400" height="150">
  <ellipse cx="200" cy="80" rx="80" ry="50" stroke="black" stroke-width="3" fill="pink"></ellipse>
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930ZuN7cnvUZw.jpg

SVG 線條

  • < line > 線條
屬性 意義
x1, x2 座標開始點
y1, y2 座標結束點

範例:繪製第一端在圓點( x0, y0 ),另外一端在( x200, y200 )的直線,粗度為2px

<svg width="400" height="200">
  <line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(0,0,255); stroke-width:2" />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930QOLlXcdfFJ.jpg

  • < polyline > 折線
屬性 意義
points 表示每個點之間的 X、Y 座標

範例:繪製端點 20,50 40,25 60,40 80,120 120,140 160,180 的折線,粗度為3px

<svg width="400" height="200">
    <polyline
      points="20,50 40,25 60,40 80,120 120,140 160,180 "
      style="fill: none; stroke: orangered; stroke-width: 3"
    />
  </svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930at1lxkGdwZ.jpg

  • < polygon > 多邊形
    數值與折線相同,只是 polygon 會產生閉合折線並填滿區塊
屬性 意義
points 表示每個點之間的 X、Y 座標

範例:繪製端點 200,10 250,190 160,180 的閉合形狀,顏色填滿為綠色,邊框粗度為3px

<svg width="400" height="200">
  <polygon
    points="200,10 250,190 160,180"
    style="fill: lime; stroke: purple; stroke-width: 1"
  />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930YB5PzBETQK.jpg

SVG 路徑、文字

  • < path > 路徑
屬性 意義
d 路徑

< path > 元素是在 SVG 中最常見的指令,它可以透過命令語言繪製任何形狀。它只有一個 d 屬性,而屬性值是由「空白間隔的命令」+「座標字串」組合而成。

所有的「空白間隔的命令」都是用一個英文字元指令,並具備兩種形式

  1. 大寫字母:表示跟隨在後方的座標是絕對座標
  2. 小寫字母:表示跟隨在後方的座標是相對座標

習慣上在一開始時,會用 M 命令移動到一個明確的位置再開始繪製。至於座標的部分,在 < path > 中的座標都沒有單位,而且可以有負值。

以下列出幾個常見的命令英文代號,但由於繪製路徑很複雜,一般我們不會自己算座標去畫圖,而是使用一些輔助工具 (例如 AI illustrator) 畫好圖片後存成SVG檔,而D3.js 也提供了函式去產生相對應的路徑。

命令英文代號

  • M, m 移動至特定位置 (不會繪製線條)
  • L, l 畫一條直線到...
  • H, h 水平線
  • V, v 垂直線
  • Z, z 把目前座標的點跟第一點連起來,並形成封閉路徑
  • C, c 立方貝茲曲線
  • S, s 從多個控制點畫立方貝茲曲線
  • Q, q 畫貝茲曲線
  • T, t 從多個控制點畫貝茲曲線
  • A, a 從目前的位置畫橢圓曲線
<svg width="400" height="200">
  <path
    d="M50 20 C80 90,40 200,250,100"
    stroke="black"
    fill="none"
    stroke-width="2"
  />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930GWBJTYOPnG.jpg

也可以透過不同線段畫出有趣的圖

<svg width="100" height="100">
    <path
      d="M25,15 L25,30
         M75,15 L75,30
         M15,50 C20,80 80,80 85,50"
      stroke="black"
      fill="none"
      stroke-width="2"
    />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930Tt3H0y3FNT.jpg

  • < text > 文字
屬性 意義
x,y 文字的座標
dx 以 x 座標為基準,平行移動文字距離(正為往右,負為往左)。
dy 以 Y 座標為基準,垂直移動文字距離(正為往上,負為往下)。
textLength 設定這段文字的長度,和 lengthAdjust ( 設定對這段文字長度的調整 ) 搭配運作
text-anchor 文字開始繪製位置 (靠左、置中、靠右對齊)
rotate 每個文字的旋轉角度,若是要整組文字一起旋轉可以使用 transform="rotate()"

特別的是,只要把屬形值改為陣列 [ ] ,這些屬性就可以針對單一字元設定。

<svg width="400" height="200">
    <text x="50,60,80" y="80,120,40" fill="blue" text-anchor="start">
      SVG 真有趣!
    </text>
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930jZGE3Y78dL.jpg


SVG的樣式、轉換屬性

看完上述SVG定義的圖形後,會發現這些標籤還跟著很多屬性的設定。有了這些屬性,我們才能設定形狀的樣式、動畫等等,以下就來介紹一些常見的屬性:

常用表現屬性:

常用表現屬性 用途
< stroke > 圖形的邊框顏色
< stroke-width > 圖形的邊框粗細
< fill > 圖形的內部填滿顏色
< font-size > 文字尺寸
< opacity > 圖形的透明度
< visibility > 圖形是否可視

.
轉換屬性:移動、旋轉、延展、推移

常用轉換屬性 用途
< rotate > 圖形旋轉
< transform > 圖形變形

.

相關補充資源

如果看完這邊後,想再更深入了解SVG的話,可以參考 W3C的SVG教學 ,裡面根據每個SVG的圖形跟樣式都有個別說明~

關於SVG的屬性,我這邊只介紹一些比較常用的~如果想看完整的屬性列表,則可以到MDN的頁面查找

.

Github Page 圖表與 Github 程式碼

最後,這邊附上本章的程式碼與圖表 GithubGithub Page,需要的人請自行取用~

今天終於平安的結束啦~明天再見!


上一篇
Day2-D3基礎介紹
下一篇
Day4- D3選取器:Selection
系列文
三十天成為D3.js v7 好手30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
alincode
iT邦研究生 5 級 ‧ 2021-11-12 07:43:15

然後呢?快說 SV! ---> 是不是少一個字?

金金 iT邦新手 1 級 ‧ 2021-11-12 09:37:22 檢舉

對耶~謝謝,立刻補上!

我要留言

立即登入留言